const PENDING = 'pendding'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'


class MyPromise {
  constructor(executer) {
    try {
      // 初始化时运行执行器函数
      executer(this.resolve, this.reject)
    } catch (e) {
      // 捕获执行器函数的错误
      this.reject(e)
    }
  }
  // 当前promise的状态
  status = PENDING
  // 初始化值
  value = undefined
  // 出错时的原因
  reason = undefined
  // 成功回调 因为可能会调用多次then所以用数组存储
  successCallback = []
  // 失败回调 同理
  failCallback = []
  // promise.all 为静态方法 接收一个数组作为参数 返回值为promise
  static all = array => {
    // 保存返回值
    let result = []
    // 用于记录完成了多少个异步函数
    let index = 0
    return new MyPromise((resolve, reject) => {
      // 将指定位置的异步方法的值放到指定的位置
      function addData(i, data) {
        result[i] = data
        index++
        // 如果全部异步函数均执行完成 返回result
        if(index === result.length){
          resolve(result)
        }
      }
      for (let i = 0; i < array.length; i++) {
        let current = array[i]
        // 判断当前函数是否为 promise 对象
        if (current instanceof MyPromise) {
          // 执行 mypromise 的 then 方法
          current.then(value => addData(i, value), reason => reject(reason))
        } else {
          addData(i, current)
        }
      }
    })
  }

  // 静态方法 始终返回一个 promise 对象
  static resolve = value => {
    // 如果值为MyPromise实例直接返回
    if(value instanceof MyPromise) return value
    return new MyPromise(resolve => resolve(value))
  }
  resolve = value => {
    // 如果状态不是等待 阻止运行
    if (this.status !== PENDING) return
    // 将状态改为成功
    this.status = FULFILLED
    this.value = value
    // this.successCallback && this.successCallback(value)
    // 执行所有存储的成功回调
    while (this.successCallback.length) {
      this.successCallback.shift()()
    }
    // console.log(value)
  }
  reject = reason => {
    // 如果状态不是等待 阻止运行
    if (this.status !== PENDING) return
    // 将状态改为失败
    this.status = REJECTED
    this.reason = reason
    // this.failCallback && this.failCallback(reason)
    // 执行所有存储的失败回调
    while (this.failCallback.length) {
      this.failCallback.shift()()
    }
  }
  then(successCallback, failCallback) {
    // successCallback 和 failCallback 赋予默认值
    successCallback = successCallback ? successCallback : value => value
    failCallback = failCallback ? failCallback : reason => { throw reason }
    // then的返回值为一个新的MyPromise实例
    let promise2 = new MyPromise((resolve, reject) => {
      // 判断当前实例的状态
      if (this.status === FULFILLED) {
        // 使用定时器的原因是为了获取返回的MyPromise(promise2)实例
        setTimeout(() => {
          try {
            const x = successCallback(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            const x = failCallback(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      } else {
        // 执行器方法为异步方法，将回调放入回调数组等待调用
        this.successCallback.push(() => {
          setTimeout(() => {
            try {
              const x = successCallback(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        // 执行器方法为异步方法，将回调放入回调数组等待调用
        this.failCallback.push(() => {
          setTimeout(() => {
            try {
              const x = failCallback(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }
    })
    return promise2
  }
  // catch方法 直接调用then
  catch = failCallback => {
    return this.then(undefined,failCallback)
  }

  finlly = callback => {
    return this.then(value => {
      return MyPromise.resolve(callback()).then( () => value)
    }, reason => {
      return MyPromise.resolve(callback()).then( reason => { throw reason })
    })
  }
}

// 处理MyPromise
function resolvePromise(promise2, x, resolve, reject) {
  // 如果返回的实例和本实例为同一个 则报错
  if (promise2 === x) {
    return reject(new TypeError('promise不能循环调用#promise'))
  }
  // 如果为MyPromise实例 调用then方法
  if (x instanceof MyPromise) {
    x.then(resolve, reject)
  } else {
    // 直接返回值
    resolve(x)
  }
}

// const p1 = () => new MyPromise((resolve, reject) => {
//   setTimeout(()=>{
//     // resolve('p1')
//     reject('p1 error')
//   },2000)
// })
// const p2 = () => new MyPromise((resolve,reject) => {
//   // resolve('p2')
//   // reject('p2 error')
// })

// p1().then((val)=>{
//   console.log(val)
// }).catch(reason => {
//   console.log(reason)
// })

// .then(val=>{
//     console.log(val)
//     return new MyPromise((resolve,reject)=>{
//       resolve('other')
//     })
// }).then(val => {
//     console.log(val)
// })

